home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
TIFF_WIN
/
TIFF.C
< prev
next >
Wrap
Text File
|
1990-04-25
|
13KB
|
342 lines
/*
Experiments in reading a TIFF file
*/
/* In this routine I prompt the user for the name of a TIFF file
If the user gives me a valid name, I will treat the file as a
TIFF file and interpret the records accordingly. I am trusting
the user to have given me the name of a TIFF file and not the
name of some other type of file. Once I have the name of the file
I read in the TIFF data and then construct an off screen CGrafPort.
the CGrafPort is very easy to create on a Macintosh and it solves
many problems dealing with scrolling and color.
The fun part of this code is where I create the Color Table and use
that to create a Color Palette.
You should read up on the palette manager in InsideMac Vol 5 and
then play around with the code to see the different effects that
you can accomplish.
*/
#include "my color.h"
#include "tiff.h"
#include <StdFilePkg.h>
#include <FileMgr.h>
#define DOTS_PER_INCH_72 0x00480000
CGrafPtr read_tiff_file(new_window)
CWindowPtr new_window;
{
OSErr io_errors;
char *my_prompt;
Point cornor_of_dialog_box;
register short even_constant, i;
short file_ref_num, number_of_file_types, nBits;
long header_size;
long value, pixels_per_line, nLines, picture_size;
char *PicbaseAddr;
SFReply the_responce_to_me;
SFTypeList my_type;
PixMapHandle tiff_map;
short max_value, min_value, photo_type, response_curve, response_unit, number_of_pm_entries;
CTabHandle color_table;
PaletteHandle picture_palette, window_palette;
CGrafPtr the_picture;
long next_IFD_offset, offset_to_the_image;
short program_resource, TIFF_res_file, number_of_clut;
CTabHandle the_clut_to_use;
RGBColor rgb_black, rgb_white;
Rect tempRect;
color_table = 0L; /* initialize the important Ptrs/Handles to zero */
tiff_map = 0L;
the_picture = 0L;
PicbaseAddr = 0L;
rgb_black.red = rgb_black.green = rgb_black.blue = 0x0000;
rgb_white.red = rgb_white.green = rgb_white.blue = 0xFFFF;
tiff_map = (PixMapHandle)NewHandle(sizeof(PixMap)); /* get RAM for the PixMap */
if(!tiff_map) return (CGrafPtr)0L; /* if I failed, return a NULL pointer */
cornor_of_dialog_box.h = 50; /* draw the SFGetFile dialog at this point */
cornor_of_dialog_box.v = 50;
my_prompt = "\pWhere is TIFF?";
number_of_file_types = 1;
my_type[0] = 'TIFF';
SFGetFile(cornor_of_dialog_box, my_prompt, (ProcPtr)0, number_of_file_types, my_type,
(ProcPtr)0, &the_responce_to_me);
if(!the_responce_to_me.good) return 0l; /* If the user didn't want to open a file with this window, return a NULL pointer */
SetWTitle(new_window, the_responce_to_me.fName);
io_errors = FSOpen(the_responce_to_me.fName, the_responce_to_me.vRefNum,
&file_ref_num); /* Open the chosen TIFF file */
header_size = (long)sizeof(tiff_header);
io_errors = FSRead(file_ref_num, &header_size, &tiff_header); /* read the TIFF header */
io_errors = SetFPos(file_ref_num, fsFromStart, tiff_header.first_IFD); /* read in the first IFD */
header_size = (long)sizeof(number_of_directories);
io_errors = FSRead(file_ref_num, &header_size, &number_of_directories); /* read how many image directories there are in the TIFF file */
header_size = (long)sizeof(tiff_directory);
ifd = (struct directory_entry *)NewPtr((long)sizeof(tiff_directory)); /* get some RAM for the IFD */
if(tiff_header.first_IFD > 0)
min_value = 0; /* the default minimum value */
max_value = 256; /* the default maximum value */
photo_type = 0; /* the default photo metric interpretation */
for(i=0; i < number_of_directories; i++)
{
header_size = (long)sizeof(tiff_directory); /* the size of a IFD record */
io_errors = FSRead(file_ref_num, &header_size, ifd); /* read the IFD */
if(ifd->type == SHORT)
value = (long)ifd->tag_value.short_value;
else if(ifd->type == LONG)
value = ifd->tag_value.long_value;
switch(ifd->tag) /* decipher the TAG */
{
case SubFileType:
break;
case ImageWidth:
pixels_per_line = value;
break;
case ImageLength:
nLines = value;
break;
case BitsPerSample:
nBits = value;
min_value = 0;
max_value = 256;
break;
case MaxSampleValue:
max_value = value;
break;
case MinSampleValue:
min_value = value;
break;
case PhotometricInterpretation:
photo_type = value;
break;
case GrayResponseUnit:
response_unit = value;
break;
case GrayResponseCurve:
response_curve = value;
break;
case StripOffsets:
offset_to_the_image = value;
}
}
header_size = (long)sizeof(long);
io_errors = FSRead(file_ref_num, &header_size, &next_IFD_offset); /* read how many image directories there are in the TIFF file */
the_picture = (CGrafPtr)NewPtr(sizeof(CGrafPort)); /* Get RAM for the color graf port */
if(!the_picture)
{
SysBeep(10);
if(color_table) DisposHandle(color_table);
if(tiff_map) DisposHandle(tiff_map);
if(the_picture) DisposPtr(the_picture);
if(PicbaseAddr) DisposPtr(PicbaseAddr);
return (CGrafPtr)0L;
}
/* now I'll go ahead and open the file and read it in */
picture_size = pixels_per_line * nLines;
PicbaseAddr = NewPtr(picture_size); /* get enough RAM to hold The TIFF picture */
if(!PicbaseAddr) /* If I don't suceed then quit */
{
SysBeep(10);
DisposHandle(tiff_map);
DisposPtr(the_picture);
return (CGrafPtr)0L;
}
/* tiff_map is a CGrafPort, here is were many parameters are set
based on what I read in from the TIFF file */
(**tiff_map).baseAddr = PicbaseAddr;
(**tiff_map).pixelSize = nBits;
(**tiff_map).rowBytes = pixels_per_line | 0x8000;
(**tiff_map).bounds.top = 0;
(**tiff_map).bounds.left = 0;
(**tiff_map).bounds.bottom = nLines;
(**tiff_map).bounds.right = pixels_per_line;
(**tiff_map).pixelType = 0;
(**tiff_map).hRes = DOTS_PER_INCH_72;
(**tiff_map).vRes = DOTS_PER_INCH_72;
(**tiff_map).cmpCount = 1;
(**tiff_map).cmpSize = (**tiff_map).pixelSize;
(**tiff_map).planeBytes = 0;
(**tiff_map).pmReserved = 0;
/*
============================== Creating the clut ================================
*/
/* Some TIFF files created on Macintosh computers will have a clut resource, lets see if this TIFF file does! */
program_resource = CurResFile(); /* lets remember which resfile is being used before we change it!! */
TIFF_res_file = OpenRFPerm(the_responce_to_me.fName, the_responce_to_me.vRefNum, fsRdPerm);
if((number_of_clut = Count1Resources('clut')) == 0)
{
/* ******************************************************************************* */
/* If I fell through to here then there isn't a clut Resource!
Create the Color Table from the TIFF parameters
*/
UseResFile(program_resource); /* reset the resource back to the program */
color_table = (CTabHandle)NewHandle((Size)(sizeof(ColorTable) +
(sizeof(ColorSpec) * (max_value - min_value)))); /* get RAM for the color TABLE */
if(!color_table)
{
SysBeep(10);
if(color_table) DisposHandle(color_table);
if(tiff_map) DisposHandle(tiff_map);
if(the_picture) DisposPtr(the_picture);
if(PicbaseAddr) DisposPtr(PicbaseAddr);
return (CGrafPtr)0L;
}
(**color_table).ctSeed = GetCTSeed();
(**color_table).ctFlags = 0;
(**color_table).ctSize = (short)(max_value - min_value);
number_of_pm_entries = (short)(max_value - min_value);
/* Now I'm going to create a color Table with Gray Scale values,
most likely there will be 256 entries, but the number of entries
actually depends of the max_value I read in from the TIFF file */
even_constant = 65535 / (max_value - min_value); /* I will evenly space the grayscale values through the color table */
if(photo_type == 1) /* photo type is a value I read from the TIFF
file. If its value is 1, then the gray
colors are ascending, and the picture looks
like a normal black and white photo. If
photo_type was 0 (Zero) then the gray scale
values are decending, and the picture looks
like a black and white negative! */
for(i= 0; i < max_value; i++)
{ /* change these values to get really interesting
effects, like multiply red by 2 and green by
4 and see what happens */
(**color_table).ctTable[i].value = i;
(**color_table).ctTable[i].rgb.red = (i * even_constant);
(**color_table).ctTable[i].rgb.green = (i * even_constant);
(**color_table).ctTable[i].rgb.blue = (i * even_constant);
}
else if(photo_type == 0)
for(i= max_value; i > 0; i--)
{
(**color_table).ctTable[i].value = max_value - i;
(**color_table).ctTable[i].rgb.red = (i * even_constant);
(**color_table).ctTable[i].rgb.green = (i * even_constant);
(**color_table).ctTable[i].rgb.blue = (i * even_constant);
}
}
/* ******************************************************************************** */
else /* A resource fork exists with a clut! Lets read it in! */
{ /* to experiment, try using ResEdit to paste a "clut"
resource into the TIFF file you're reading, this
program will then use that clut to create the Palette,
This is a quick way to give your TIFF pictures a "false"
color representation! */
color_table = (CTabHandle)Get1IndResource('clut', 1);/* just get the "FIRST" clut to use */
for(i = 0; i < (**color_table).ctSize; i++)
(**color_table).ctTable[i].value = i; /* this is necessary for Color Quick
has to know what colors go with
what 8 bit values in the TIFF
file */
number_of_pm_entries = (**color_table).ctSize;
UseResFile(program_resource);
}
/* now here is where the color palette is created, the palette is used
to give the window the colors that are to be used in displaying the
TIFF picture.
*/
picture_palette = NewPalette(number_of_pm_entries, color_table,
pmTolerant, 0x0000); /* trying changing pmTolerant parameter to
something else ( see Inside Mac vol 5)
and see what happens. The 0x0000 tells
the palette manager to make exact matches
to display the colors on screen
*/
if(!picture_palette) /* if i couldn't get enought RAM for the palette, bail out! */
{
SysBeep(10);
if(color_table) DisposHandle(color_table);
if(tiff_map) DisposHandle(tiff_map);
if(the_picture) DisposPtr(the_picture);
if(PicbaseAddr) DisposPtr(PicbaseAddr);
return (CGrafPtr)0L;
}
SetEntryColor(picture_palette, 0, &rgb_black); /* according to Inside Mac Vol 5,
the first two colors in the
palette should be black and
white, this tells the
palette manager which
positions to use for
those colors. See page V 158 in Inside Mac */
SetEntryColor(picture_palette, 1, &rgb_white);
SetEntryUsage(picture_palette, 0, 0x0000, 0x0000);
SetEntryUsage(picture_palette, 1, 0x0002, 0x0000);
HLock(color_table);
(**tiff_map).pmTable = color_table; /* stick our color table into the palette! */
HUnlock(color_table);
/*
=================================================================================
*/
GetPort(&savedPort); /* SAVE THE CURRENT P0RT */
OpenCPort(the_picture); /* now make our CGrafPort the default port */
InitCPort(the_picture); /* initialize our CGrafPort to the default values */
PmForeColor(1); /* here I tell the Palette Manager which colors to use for the foreground and background drawing */
PmBackColor(0);
SetPort(the_picture); /* make my offscreen CGrafPort the default port */
SetPortPix(tiff_map); /* now make the PixMap I've created be the CGrafPort's PixMap */
SetPort(savedPort);
window_palette = GetPalette(new_window); /* if the window already has a palette, then get rid of it */
if(window_palette)
DisposePalette(window_palette);
SetPalette(new_window, picture_palette, TRUE); /* make our palette the window's palette, the TRUE
parameter tells the Mac that I want update
events generated whenever the window's
palette changes, for fun try changing it to
FALSE */
ActivatePalette(new_window); /* now turn on the palette */
SetPort(new_window);
/*
now read in the TIFF picture and stick
it into the offscreen CGrafPort, the
update routine will take care of
displaying the image
*/
io_errors = SetFPos(file_ref_num, fsFromStart, offset_to_the_image); /* read in the first IFD */
io_errors = FSRead(file_ref_num, &picture_size, PicbaseAddr);
io_errors = FSClose(file_ref_num);
DisposPtr(ifd); /* clean up after yourself */
return the_picture;
}